package com.zhlq.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日期字符串操作工具类，包含有各种各样的日期形式相关转化
 * @author zhangy
 *
 */
public class DateUtil {
	
	/*--------------- 常用格式化定义 ---------------------*/
	/** 常用格式的纯数字格式 */
	private static SimpleDateFormat formatNumber = new SimpleDateFormat("yyyyMMddHHmmss");
	/** 常用格式的纯数字格式，精确到毫秒 */
	private static SimpleDateFormat formatNumberExact = new SimpleDateFormat("yyyyMMddHHmmssSSS");
	/** 常用格式，只含日期 */
	private static SimpleDateFormat formatOnlyDate = new SimpleDateFormat("yyyy-MM-dd");
	/** 常用格式，只含数字日期 */
	private static SimpleDateFormat formatNumDate = new SimpleDateFormat("yyyyMMdd");
	/** 常用格式 */
	private static SimpleDateFormat formatGeneral = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/** 常用格式，精确到毫秒 */
	private static SimpleDateFormat formatGeneralExact = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
	
	/*--------------- 操作系统相关 ---------------------*/
	
	/** 取得当前操作系统日期时间的纯数字形式：yyyyMMddHHmmss */
	public static String dateNumber(){
		return formatNumber.format(new Date());
	}
	
	/** 取得当前操作系统日期时间的纯数字形式：yyyyMMddHHmmssSSS，精确到毫秒 */
	public static String dateNumberExact(){
		return formatNumberExact.format(new Date());
	}
	
	/** 取得当前操作系统日期时间的只含日期形式：yyyy-MM-dd */
	public static String date(){
		return formatOnlyDate.format(new Date());
	}
	
	/** 取得当前操作系统日期时间的只含日期形式：yyyyMMdd */
	public static String NumDate(){
		return formatNumDate.format(new Date());
	}
	
	/** 取得当前操作系统日期时间的常用日期时间形式：yyyy-MM-dd HH:mm:ss */
	public static String dateTime(){
		return formatGeneral.format(new Date());
	}
	
	/** 取得当前操作系统日期时间的常用日期时间形式：yyyy-MM-dd HH:mm:ss,SSS，精确到毫秒 */
	public static String dateTimeExact(){
		return formatGeneralExact.format(new Date());
	}
	
	/*--------------- 日期对象相关：重载 ---------------------*/
	
	/** 取得日期时间的纯数字形式：yyyyMMddHHmmss */
	public static String dateNumber(Date d){
		return formatNumber.format(d);
	}
	
	/** 取得日期时间的纯数字形式：yyyyMMddHHmmssSSS，精确到毫秒 */
	public static String dateNumberExact(Date d){
		return formatNumberExact.format(d);
	}
	
	/** 取得日期时间的日期形式：yyyy-MM-dd */
	public static String date(Date d){
		return formatOnlyDate.format(d);
	}
	
	/** 取得当前操作系统日期时间的只含日期形式：yyyyMMdd */
	public static String NumDate(Date d){
		return formatNumDate.format(d);
	}
	
	/** 取得日期时间的常用日期时间形式：yyyy-MM-dd HH:mm:ss */
	public static String dateTime(Date d){
		return formatGeneral.format(d);
	}
	
	/** 取得日期时间的常用日期时间形式：yyyy-MM-dd HH:mm:ss,SSS，精确到毫秒 */
	public static String dateTimeExact(Date d){
		return formatGeneralExact.format(d);
	}
	
	/*--------------- 其它 ---------------------*/
	
	/**
	 * 直接使用指定格式，格式化日期为指定的样式style 
	 * @param date 需要格式化的日期对象
	 * @param style 目标样式
	 */
	public static String format(Date date, String style){
		return new SimpleDateFormat(style).format(date);
	}
	
	/** 将标准格式(yyyy-MM-dd HH:mm:ss)的日期时间字符串转换为日期对象 
	 * @throws ParseException */
	public static Date parseDateTime(String sdate) throws ParseException{
		return formatGeneral.parse(sdate);
	}
	
	/**
	 * 使用指定格式将日期时间字符串转换为日期对象 
	 * @param sdate 需要转换的日期时间字符串
	 * @param style 日期时间字符串的格式样式
	 * @return
	 * @throws ParseException
	 */
	public static Date parseDateTime(String sdate, String style) throws ParseException{
		return new SimpleDateFormat(style).parse(sdate);		
	}
	
	/**
	 * 将纯数字的日期时间还原成常用格式(yyyy-MM-dd)或 (yyyy-MM-dd HH:mm:ss)，仅将对应位数拆开重组，不做数值校检<br/>
	 * 自动匹配8位(yyyyMMdd) 与 14位(yyyyMMddHHmmss)的形式，其它位数无法匹配以原样返回
	 * @param number 纯数字形式的日期时间字符串
	 * @return 常用格式(yyyy-MM-dd)或 (yyyy-MM-dd HH:mm:ss)的日期时间字符串
	 */
	public static String numberToDate(String number){
		if(number.length() == 8){
			return number.substring(0,4) + "-" + number.substring(4,6) + "-" + number.substring(6, 8);
		}else if(number.length() == 14){
			return number.substring(0,4) + "-" + number.substring(4,6) + "-" + number.substring(6, 8) + " "
				+ number.substring(8, 10) + ":" + number.substring(10, 12) + ":"  + number.substring(12, 14);
		}else{
			return number;
		}		
	}
	
	/**
	 * 匹配字符串中第一个出现的日期格式化字符串“{yyyMMdd...}”，
	 * 并将该字符串（包括大括号，也必须包含大括号）使用指定的格式的当前系统日期替换。<br/>
	 * 例如：abc-{yyyy-MM-dd HH:mm:ss}-ef执行该法后返回的结果是abc-2012-12-21 12:22:21-ef。（注意具体时间以计算机为准）
	 * @param str
	 * @return
	 */
	public static String match(String str){
		return match(str, new Date());
	}
	
	/**
	 * 匹配字符串中第一个出现的日期格式化字符串“{yyyMMdd...}”，并将该字符串（包括大括号，也必须包含大括号）使用指定的格式的日期date替换。<br/>
	 * 例如：abc-{yyyy-MM-dd HH:mm:ss}-ef执行该法后返回的结果是abc-2012-12-21 12:22:21-ef。（注意具体时间以date为准）
	 * @param str
	 * @return
	 */
	public static String match(String str, Date date){
		// 匹下日期格式化字符串
		int start = str.indexOf("{");
		int end = str.indexOf("}");
		if (start == -1 || end == -1) {
			return str;
		} else {
			String fmt = str.substring(start + 1, end);
			String day = format(date, fmt);
			return str.replace("{" + fmt + "}", day);
		}
	}
	
	/**
	 * 匹配字符串中第一个出现的日期格式化字符串“{yyyMMdd...}”，并将该字符串（包括大括号，也必须包含大括号）使用指定日期date字符串替换。<br/>
	 * 例如：str="abc-{yyyy-MM-dd HH:mm:ss}-ef",<br/>
	 * 		date="2012-12-21 12:22:21",执行该法后返回的结果是abc-2012-12-21 12:22:21-ef。
	 * @param str
	 * @return
	 */
	public static String match(String str, String date){
		// 匹下日期格式化字符串
		int start = str.indexOf("{");
		int end = str.indexOf("}");
		if (start == -1 || end == -1) {
			return str;
		} else {
			String fmt = str.substring(start + 1, end);
			return str.replace("{" + fmt + "}", date);
		}
	}
	
	/**将字符串日期转换成Date类型*/
	public static Date sDateParse2(String sDate){
		try{
			SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			return sd.parse(sDate);
		
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 传入String类型的日期，返回 boolean类型，true为正确日期格式，false为格式错误
	 * 注意：不包含时间，正确的格式如：2014-07-28，不正确的如：2014-7-28
	 */
	public static boolean validDateNotTime(String str){
		final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		try{
	        Date date = (Date)formatter.parse(str);
	        return str.equals(formatter.format(date));
	    }catch(Exception e){
	       return false;
	    }
	}
	
}
